const db = uniCloud.database()
const $ = db.command
const groupCollection = db.collection('Group') // 假设集合名为 groups (与schema对应)
const userCollection = db.collection('linli-user') // 用户集合 (关联ownId)
const now = Date.now()
const linliUtils = require('linliUtils')

module.exports = {
	_before: async function() {
		// 前置校验：获取当前登录用户ID (根据实际登录机制调整)
		// this.userId = this.getClientInfo().userId // 需配合权限中间件获取真实用户ID
		// if (!this.userId) {
		//   throw new Error('请先登录')
		// }
	},

	/**
	 * 创建群聊
	 * @param {string} userId 创建者Id
	 * @param {Object} params 创建参数
	 * @param {string} params.groupName 群名
	 * @param {string} params.signature 群介绍
	 * @param {Object} params.location 位置中心点 ({latitude, longitude})
	 * @param {number} params.radius 范围半径 (米)
	 * @param {boolean} params.needApproval 是否需要群主同意入群 (默认true)
	 * @param {boolean} params.visibleInRange 是否仅位置范围内可见 (默认true)
	 * @param {Array} [params.groupPicPath] 群头像和群相片，群头像为0索引
	 * @returns {Object} 群信息
	 */
	async createGroup(userId, params) {
		const {
			groupName,
			signature,
			location,
			groupUser, // [{userId: this.userId, role: 'owner', joinTime: now}],
			radius,
			needApproval = true,
			visibleInRange = true,
			groupPicPath
		} = params

		// 参数校验
		if (!groupName || !location || !radius) {
			throw new Error('群名、位置和范围为必填项')
		}

		// 注意：此处 forEach 中的 async 函数不会等待，请使用 for...of 或 Promise.all
		var newGroupUser = []
		for (const item of groupUser) {
			if (item.userId) {
				newGroupUser.push({
					...item,
					joinTime: now,
					role: userId === item.userId ? 'owner' : 'member'
				})
			} else {
				const res = await userCollection.where({
					userTel: item.userTel
				}).field({
					userId: true
				}).get()
				if (res.data.length > 0) {
					const newId = res.data[0].userId
					newGroupUser.push({
						...item,
						userId: newId,
						joinTime: now,
						role: 'member',
						joinType: 'invited'
					})
				} else {
					// 不建议在创建群聊时自动创建用户，这可能导致垃圾数据
					// 建议先检查用户是否存在，不存在则提示邀请失败
					throw new Error(`用户 ${item.userTel} 不存在，无法邀请入群`)
				}
			}
		}

		const newParam = {
			...params,
			groupUser: [...newGroupUser]
		}

		// 生成群ID (可自定义规则)
		const groupId = `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`

		// 获取群主信息
		const userRes = await userCollection.where({
			userId: userId
		}).field({
			userId: 1,
			nicName: 1,
			nicPic: 1
		}).get()
		if (userRes.data.length === 0) {
			throw new Error('用户信息不存在')
		}

		// 插入群数据
		const groupData = {
			groupId,
			...newParam,
			ownId: userId,
			ownInfo: userRes.data[0], // 群主信息
			registTime: now,
			status: 'active', // 群状态：active-正常，dissolved-已解散
			pendingUsers: [] // 待审批的入群申请
		}

		await groupCollection.add(groupData)

		// 通知所有成员加入群聊（更新用户的 groups 字段）
		const membersId = groupData.groupUser.map(item => item.userId)
		// 使用 Promise.all 等待所有更新完成
		await Promise.all(membersId.map(id =>
			userCollection.where({
				userId: id
			}).update({
				groups: $.push({
					groupId: groupId,
					isAgree: false
				})
			})
		))

		return {
			code: 0,
			message: '群聊创建成功',
			data: {
				groupId,
				...groupData
			}
		}
	},

	/**
	 * 解散群聊 (仅群主可操作)
	 * @param {string} userId 用户Id
	 * @param {string} groupId 群ID
	 * @returns {Object} 操作结果
	 */
	async dissolveGroup(userId, {
		groupId
	}) {
		if (!groupId) {
			throw new Error('群ID不能为空')
		}

		// 校验群存在且当前用户是群主
		const group = await groupCollection.where({
			groupId,
			status: 'active'
		}).get()
		if (group.data.length === 0) {
			throw new Error('群聊不存在或已解散')
		}
		if (group.data[0].ownId !== userId) {
			throw new Error('无权限解散群聊 (仅群主可操作)')
		}

		// 更新群状态为已解散
		await groupCollection.where({
			groupId
		}).update({
			status: 'dissolved',
			dissolveTime: Date.now()
		})

		// 可选：通知所有成员群已解散（更新其 groups 字段）
		const membersId = group.data[0].groupUser.map(item => item.userId);
		await Promise.all(membersId.map(id =>
			userCollection.where({
				userId: id
			}).update({
				groups: $.pull({
					groupId: groupId
				})
			})
		));

		return {
			code: 0,
			message: '群聊已解散'
		}
	},

	/**
	 * 批量邀请用户入群 (群主或管理员可操作，无需审批)
	 * @param {string} userId 操作人ID (邀请者)
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @param {Array<string>} params.clientIds 被邀请用户ID数组
	 * @returns {Object} 操作结果汇总
	 */
	async inviteUser(userId, {
		groupId,
		clientIds
	}) {
		// 1. 前置参数与状态校验 (只做一次)
		if (!groupId) {
			throw new Error('群ID不能为空');
		}
		if (!Array.isArray(clientIds) || clientIds.length === 0) {
			throw new Error('被邀请用户ID列表必须是一个非空数组');
		}

		// 校验群状态
		const groupRes = await groupCollection.where({
			groupId,
			status: 'active'
		}).get();
		if (groupRes.data.length === 0) {
			return {
				code: -1,
				message: '群已解散'
			}
		}
		const groupData = groupRes.data[0];

		// 校验邀请者权限
		// const inviter = groupData.groupUser.find(u => u.userId === userId);
		// if (!inviter || !['owner', 'admin'].includes(inviter.role)) {
		//     throw new Error('无权限邀请用户 (仅群主或管理员可操作)');
		// }

		// 2. 批量处理邀请
		const results = {
			success: [],
			fail: []
		};

		// 使用 Promise.all 并行处理所有邀请，以提高效率
		await Promise.all(clientIds.map(async (clientId) => {
			try {
				// 对每个用户执行邀请逻辑
				// 校验被邀请用户是否已在群内
				const isInGroup = groupData.groupUser.some(u => u.userId === clientId);
				if (isInGroup) {
					results.fail.push({
						clientId,
						reason: '该用户已在群内'
					});
					return; // 跳过后续步骤
				}

				// 获取被邀请用户信息
				const userRes = await userCollection.where({
					userId: clientId
				}).field({
					userId: 1,
					nicName: 1,
					nicPic: 1
				}).get();
				if (userRes.data.length === 0) {
					results.fail.push({
						clientId,
						reason: '被邀请用户不存在'
					});
					return; // 跳过后续步骤
				}

				// 添加用户到群成员列表
				await groupCollection.where({
					groupId
				}).update({
					groupUser: $.push({
						userId: clientId,
						role: 'member',
						joinTime: Date.now(),
						joinType: 'invited'
					})
				});

				// 更新被邀请用户的 groups 字段
				await userCollection.where({
					userId: clientId
				}).update({
					groups: $.push({
						groupId: groupId,
						isAgree: true
					})
				});

				// 如果所有步骤都成功
				results.success.push({
					clientId,
					message: '邀请成功'
				});

			} catch (error) {
				// 捕获单个用户邀请过程中可能发生的其他未知错误
				console.error(`邀请用户 ${clientId} 失败:`, error);
				results.fail.push({
					clientId,
					reason: `邀请失败: ${error.message}`
				});
			}
		}));

		// 3. 返回汇总结果
		return {
			code: 0,
			message: `批量邀请处理完成。成功: ${results.success.length} 人, 失败: ${results.fail.length} 人。`,
			data: results
		};
	},
	/**
	 * 修改群名称 (仅群主可操作)
	 * @param {string} userId 操作人ID
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @param {string} params.newGroupName 新的群名称
	 * @returns {Object} 操作结果
	 */
	async editGroupName(userId, {
		groupId,
		newGroupName
	}) {
		if (!groupId || !newGroupName) {
			throw new Error('群ID和新群名称不能为空')
		}
		if (newGroupName.length > 30) { // 限制群名长度
			throw new Error('群名称过长，请控制在30个字符以内')
		}

		// 1. 校验群存在且为活跃状态
		const groupRes = await groupCollection.where({
			groupId,
			status: 'active'
		}).get();
		if (groupRes.data.length === 0) {
			throw new Error('群聊不存在或已解散');
		}
		const groupData = groupRes.data[0];

		// 2. 校验操作人是否为群主
		if (groupData.ownId !== userId) {
			throw new Error('无权限修改群名称 (仅群主可操作)');
		}

		// 3. 更新群名称
		await groupCollection.where({
			groupId
		}).update({
			groupName: newGroupName
		});

		return {
			code: 0,
			message: '群名称修改成功'
		};
	},

	/**
	 * 申请入群 (用户主动申请)
	 * @param {string} userId 申请人ID
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @param {Object} [params.userLocation] 用户当前位置 ({latitude, longitude})
	 * @returns {Object} 操作结果
	 */
	async applyJoin(userId, {
		groupId,
		userLocation
	}) {
		if (!groupId) {
			return {
				code: -1,
				message: '群ID不能为空'
			}
		}

		const groupRes = await groupCollection.where({
			groupId,
			status: 'active'
		}).get()
		if (groupRes.data.length === 0) {
			return {
				code: -1,
				message: '群不存在或已解散'
			}
		}
		const groupData = groupRes.data[0]

		// 检查是否已在群内
		if (groupData.groupUser.some(u => u.userId === userId)) {
			return {
				code: -2,
				message: '您已在群内'
			}
		}

		// 检查是否已在待审批列表
		if (groupData.pendingUsers && groupData.pendingUsers.some(u => u.userId === userId)) {
			return {
				code: -3,
				message: '您的入群申请已提交，请等待群主同意'
			}
		}

		// 范围校验
		if (groupData.visibleInRange && userLocation) {
			const distance = this.calcDistance(
				userLocation.latitude, userLocation.longitude,
				groupData.location.latitude, groupData.location.longitude
			)
			if (distance > groupData.radius) {
				return {
					code: -4,
					message: '您不在群的可见范围内，无法申请入群'
				}
			}
		}

		// 获取申请人信息
		const userRes = await userCollection.where({
			userId
		}).field({
			userId: 1,
			nicName: 1,
			nicPic: 1
		}).get()
		if (userRes.data.length === 0) {
			throw new Error('申请人信息未找到')
		}

		// 根据群设置决定是直接加入还是需要审批
		const needApproval = groupData.needApproval !== false;
		if (needApproval) {
			// 需要审批
			await groupCollection.where({
				groupId
			}).update({
				pendingUsers: $.push({
					userId: userId,
					userInfo: userRes.data[0],
					applyTime: Date.now()
				})
			})
			return {
				code: 0,
				message: '入群申请已提交，请等待群主同意'
			}
		} else {
			// 无需审批，直接加入
			await groupCollection.where({
				groupId
			}).update({
				groupUser: $.push({
					userId: userId,
					role: 'member',
					joinTime: Date.now(),
					joinType: 'applied'
				})
			})
			await userCollection.where({
				userId
			}).update({
				groups: $.push({
					groupId: groupId,
					isAgree: true
				})
			})
			return {
				code: 1,
				message: '入群成功'
			}
		}
	},

	/**
	 * 同意入群申请 (仅群主可操作)
	 * @param {string} userId 操作人ID (群主)
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @param {string} params.clientId 申请人ID
	 * @returns {Object} 操作结果
	 */
	async approveApply(userId, {
		groupId,
		clientId
	}) {
		if (!groupId || !clientId) {
			throw new Error('群ID和用户ID不能为空')
		}

		const groupRes = await groupCollection.where({
			groupId,
			status: 'active'
		}).get()
		if (groupRes.data.length === 0) {
			throw new Error('群聊不存在或已解散')
		}
		const groupData = groupRes.data[0]

		if (groupData.ownId !== userId) {
			throw new Error('无权限审批 (仅群主可操作)')
		}

		// 检查申请是否存在
		const pendingIndex = groupData.pendingUsers.findIndex(u => u.userId === clientId)
		if (pendingIndex === -1) {
			throw new Error('该用户无入群申请')
		}

		// 从待审批列表移除，并添加到成员列表
		const approvedUser = groupData.pendingUsers[pendingIndex];
		await groupCollection.where({
			groupId
		}).update({
			pendingUsers: $.pull({
				userId: clientId
			}),
			groupUser: $.push({
				userId: clientId,
				role: 'member',
				joinTime: Date.now(),
				joinType: 'applied'
			})
		})

		// 更新用户的 groups 字段
		await userCollection.where({
			userId: clientId
		}).update({
			groups: $.push({
				groupId: groupId,
				isAgree: true
			})
		})

		return {
			code: 0,
			message: '已同意入群申请'
		}
	},
	/**
	 * 踢出群聊 (仅群主可操作)
	 * @param {string} userId 操作人ID (群主)
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @param {string} params.clientId 被踢用户ID
	 * @returns {Object} 操作结果
	 */
	async kickUser(userId, {
		groupId,
		clientId
	}) {
		try {
			if (!groupId || !clientId) {
				// throw new Error('群ID和用户ID不能为空');
				return {
					code: -1,
					message: '群ID和用户ID不能为空'
				};
			}
			if (userId === clientId) {
				// throw new Error('不能将自己踢出群聊');
				return {
					code: -1,
					message: '不能将自己踢出群聊'
				};
			}

			const groupRes = await groupCollection.where({
				groupId,
				status: 'active'
			}).get();
			if (groupRes.data.length === 0) {
				// throw new Error('群聊不存在或已解散');
				return {
					code: -1,
					message: '群聊不存在或已解散'
				};
			}
			const groupData = groupRes.data[0];

			if (groupData.ownId !== userId) {
				// throw new Error('无权限踢人 (仅群主可操作)');
				return {
					code: -1,
					message: '无权限踢人 (仅群主可操作)'
				};
			}

			const isInGroup = groupData.groupUser.some(u => u.userId === clientId);
			if (!isInGroup) {
				// throw new Error('该用户不在群内');
				return {
					code: -1,
					message: '该用户不在群内'
				};
			}

			// 从群成员列表移除 - 修正 $.pull 的语法
			await groupCollection.where({
				groupId
			}).update({
				groupUser: $.pull('groupUser', {
					userId: clientId
				})
			});

			// 从用户的 groups 字段中移除该群
			await userCollection.where({
				userId: clientId
			}).update({
				groups: $.pull('groups', {
					groupId: groupId
				})
			});

			return {
				code: 0,
				message: '已将用户踢出群聊'
			};

		} catch (error) {
			// 捕获系统级异常，如数据库连接失败等
			console.error("踢人操作发生系统错误:", error);
			return {
				code: -999,
				message: '服务器内部错误，请稍后再试',
				error: error.message // 可在开发环境返回详细错误，生产环境移除
			};
		}
	},
	/**
	 * 退出群聊 (群成员主动操作)
	 * @param {string} userId 操作人ID (即要退出群聊的用户自己)
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @returns {Object} 操作结果
	 */
	async quitGroup(userId, {
		groupId
	}) {
		try {
			// 1. 参数校验
			if (!groupId || !userId) {
				return {
					code: -1,
					message: '群ID和用户ID不能为空'
				};
			}

			// 2. 校验群状态
			const groupRes = await groupCollection.where({
				groupId,
				status: 'active'
			}).get();
			if (groupRes.data.length === 0) {
				return {
					code: -1,
					message: '群聊不存在或已解散'
				};
			}
			const groupData = groupRes.data[0];

			// 3. 校验用户是否在群内
			const isInGroup = groupData.groupUser.some(u => u.userId === userId);
			if (!isInGroup) {
				return {
					code: -1,
					message: '你不在该群聊中'
				};
			}

			// 4. 执行退出操作
			// 4.1 从群的成员列表中移除该用户
			await groupCollection.where({
				groupId
			}).update({
				groupUser: $.pull('groupUser', {
					userId: userId
				})
			});

			// 4.2 从用户的群列表中移除该群
			await userCollection.where({
				userId: userId
			}).update({
				groups: $.pull('groups', {
					groupId: groupId
				})
			});

			// 5. 返回成功结果
			return {
				code: 0,
				message: '已成功退出群聊'
			};

		} catch (error) {
			// 捕获系统级异常
			console.error("退出群聊操作发生系统错误:", error);
			return {
				code: -999,
				message: '服务器内部错误，请稍后再试'
			};
		}
	},

	/**
	 * 分享群卡片
	 * @param {string} userId 用户ID
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @returns {Object} 群卡片信息
	 */
	async shareGroupCard(userId, {
		groupId
	}) {
		if (!groupId) {
			throw new Error('群ID不能为空')
		}

		const group = await groupCollection.where({
			groupId,
			status: 'active'
		}).field({
			groupId: 1,
			groupName: 1,
			signature: 1,
			groupPicPath: 1,
			ownInfo: {
				nicName: 1,
				nicPic: 1
			},
			memberCount: $.size('$groupUser')
		}).get()

		if (group.data.length === 0) {
			throw new Error('群聊不存在或已解散')
		}

		return {
			code: 0,
			data: {
				...group.data[0],
				shareTime: Date.now()
			}
		}
	},

	/**
	 * 获取用户加入的所有群
	 * @param {string} userId 用户ID
	 * @returns {Object} 群列表
	 */
	async getGroup(userId) {
		try {
			const userRes = await userCollection.where({
				userId
			}).field({
				groups: true
			}).get()
			if (!userRes.data.length || !userRes.data[0].groups || userRes.data[0].groups.length === 0) {
				return {
					code: -1,
					msg: '该用户未加入任何群聊'
				}
			}

			const groupIds = userRes.data[0].groups.map(item => item.groupId)
			const groupRes = await groupCollection.where({
				groupId: $.in(groupIds),
				status: 'active' // 只返回活跃的群
			}).get()

			return {
				code: 0,
				data: groupRes.data
			}
		} catch (e) {
			console.error(e)
			return {
				code: -1,
				msg: '获取群列表失败',
				error: e.message
			}
		}
	},

	/**
	 * 根据群ID获取群详情
	 * @param {string} userId 用户ID (用于权限校验，例如查看非公开群)
	 * @param {Object} params 参数
	 * @param {string} params.groupId 群ID
	 * @returns {Object} 群详情
	 */
	async getGroupBygroupId(userId, {
		groupId
	}) {
		
		try {
			const res = await groupCollection.where({
				groupId
			}).get()
			if (res.data.length>0) {
				const groupUsers = res.data[0].groupUser
		
				const idx = groupUsers.findIndex(item => item.userId === userId)
				if (idx === -1) {
					return {
						code: false,
						errMsg: '已退出群'
					}
				}

				// 可以在这里添加权限校验逻辑，例如：
				// if (res.data[0].visibleInRange) { ... }
				return {
					code: true,
					data: res.data[0]
				}
			} else {
				return {
					code: false,
					errMsg: '群已解散'
				}
			}
		} catch (e) {
			console.error(e)
			return {
				code: false,
				errMsg: '查找出错',
				error: e.message
			}
		}
	},

	/**
	 * 辅助方法：计算两点地理距离 (米)
	 * @param {number} lat1 纬度1
	 * @param {number} lon1 经度1
	 * @param {number} lat2 纬度2
	 * @param {number} lon2 经度2
	 * @returns {number} 距离 (米)
	 */
	calcDistance(lat1, lon1, lat2, lon2) {
		const R = 6371e3; // 地球半径 (米)
		const φ1 = lat1 * Math.PI / 180;
		const φ2 = lat2 * Math.PI / 180;
		const Δφ = (lat2 - lat1) * Math.PI / 180;
		const Δλ = (lon2 - lon1) * Math.PI / 180;
		const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
			Math.cos(φ1) * Math.cos(φ2) *
			Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
		const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		return R * c;
	}
}